package pCloud.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.HashMap;

import pCloud.acesscontrol.PCloudPDP;
import pCloud.acesscontrol.PCloudPEP;
import pCloud.crypto.kpabe.ACInstanceMessage;
import pCloud.crypto.kpabe.CipherMessage;
import pCloud.crypto.kpabe.UKMessage;
import pCloud.message.DatabaseReply;
import pCloud.message.DatabaseRequest;
import pCloud.message.DatabaseSlidingWindowRequest;
import pCloud.message.Message;
import pCloud.message.NumberMessage;
import pCloud.message.PolicyFile;
import pCloud.message.PolicyManagementReply;
import pCloud.message.PolicyManagementRequest;
import pCloud.message.PolicyQueryReply;
import pCloud.message.ReplyMessage;
import pCloud.message.RequestFile;
import pCloud.message.cloud.DataMessage;
import pCloud.message.cloud.HandShakeMessage;
import pCloud.server.DatabaseHandle;
import pCloud.transport.SocketTransportHandle;
import pCloud.transport.TransportHandle;

/**
 * @author ttadinh
 * Impelement the cloud server. Maintain the conenction map
 */
public class CloudServerProtocol extends ProtocolHandle {

	AccessControlHandle accessControlHandler = null;	
	int policyCounter;
	int requestCounter;
	CloudCryptoHandle cch; 
	public PCloudPEP pep;
	public PCloudPDP pdp;
	
	public void initCloud(AccessControlHandle ach){		
		this.initializeAccessControlHandler(ach);		
		this.cch = new CloudCryptoHandle(this);		
	}
	
	private void initializeAccessControlHandler(AccessControlHandle ach) {
		this.accessControlHandler = ach;		
		this.policyCounter = 0;
		this.requestCounter = 0;
		this.pdp = new PCloudPDP();
		this.pdp.init();
		this.pep = new PCloudPEP(this.pdp);
	}

	

	@Override
	public void receive(Object o) throws Exception {
		this.handleCloudMessage((Message) o);
	}

	@Override
	public void send(Object m) throws Exception {
		this.conn.send(m);

	}

	public void sendToUser(int id, Message msg) throws Exception{
		this.communicator.getCloudConnectionToUser(id).send(msg);
	}
	
	private void handleCloudMessage(Message msg) throws Exception{
		if (msg instanceof HandShakeMessage){
			this.addNewConnection((HandShakeMessage)msg);			
		}
		else if (msg instanceof DataMessage)
			this.handleDataMessage((DataMessage)msg);
		else if (msg instanceof ACInstanceMessage){
			this.cch.handleInitMessage((ACInstanceMessage)msg);
		}
		else if (msg instanceof UKMessage){
			this.cch.handleUserKeyMessage((UKMessage)msg);
		}
		else if (msg instanceof CipherMessage){
			this.cch.handleCipherMessage((CipherMessage)msg);
		}
	}
	
	//forward to all users
	private void handleDataMessage(DataMessage dm) throws Exception{
		System.out.println("Got a DataMessage");
		dm.setMessageType(Message.FROM_CLOUD);
		this.sendToAllUser(dm);
	}
		
	private void addNewConnection(HandShakeMessage hsm) throws Exception {
		System.out.println("got handshake message");
		if (hsm.isFromOwner())
			this.communicator.addCloudConnectionToOwner(hsm.getId(),
					this.getTransportHanlde());
		else
			this.communicator.addCloudConnectionToUser(hsm.getId(),
					this.getTransportHanlde());
	}
	
	private void sendToAllUser(Message m) throws Exception{
		this.communicator.sendToAllUsers(m);
	}
}
